using CfgTable;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;
using System.Collections.Generic;

namespace IQIGame.Onigao.Logic
{
    /// <summary>
    /// npc惯常（重复）剧本表演组件
    /// 用于让npc根据策划配置不断的进行常规的表演，例如到指定地点打水，再到指定地点去浇花
    /// </summary>
    public class LgEntityRoutineActComponent : LogicBaseEntityComponent, IInterruptibleComponent
    {
        private static int _checkFrameDuration = (int)(0.1f * LgLevelConst.FrameRate);
        private LevelEntity _entity;
        private List<LevelEntity> _notifyEntityList;
        private LgNpcNavAssistantComponent _navCom;
        private CfgLevelRoutineAct _curActCfg;
        private int _actStartFrame;
        private int _checkElapsedFrame;
        private bool _isInHouse;

        public override uint MaxStore => 50;
        public bool isPausing { get; private set; }
        public bool isActive { get; private set; }

        public override void Awake(BaseEntity entity)
        {
            _entity = entity as LevelEntity;
            _notifyEntityList = new List<LevelEntity>() { _entity };
            _isInHouse = CalcIsInHouse();
        }

        private bool CalcIsInHouse()
        {
            bool isInHouse = false;
            Vector3Logic myPosition = _entity.position;
            LevelRegion region = _entity.region;
            List<LevelEntity> entities = ListPool<LevelEntity>.Get();
            {
                region.terrain.BvhSearchEntity(entities, myPosition, _entity.triggerRectBoxSize, 0);
                foreach (LevelEntity entity in entities)
                {
                    if (entity != _entity && entity.HasDynamicParam(EntityDynamicParamType.House)
                        && entity.IsContains(myPosition) && entity.IsInTriggerRectHeightRange(myPosition))
                    {
                        isInHouse = true;
                        break;
                    }
                }
                ListPool<LevelEntity>.Put(entities);
            }
            return isInHouse;
        }

        public void Play(int actId)
        {
            Stop();
            if (actId <= 0)
            {
                return;
            }
            _navCom = _entity.AddComponent<LgNpcNavAssistantComponent>();
            _curActCfg = TableCenter.levelRoutineAct.Get(actId);
            if (_curActCfg == null)
            {
                LogicLog.LogError($"找不到循环表演(RoutineAct)配置，id：{actId}");
                return;
            }
            if (_entity.isAvailable)
            {
                Active();
            }
        }

        public void Active()
        {
            if (isActive || _curActCfg == null)
                return;
            DoAction();
            isActive = true;
        }

        private void DoAction()
        {
            IReadOnlyList<int> paramList1 = _curActCfg.ParamList[0];
            switch (_curActCfg.Type)
            {
                case LgLevelRoutineActType.PlayAnimation:
                    PlayEntityAnimation(paramList1[0]);
                    break;
                case LgLevelRoutineActType.Navigation:
                    int elementLength = 4;
                    LogicLevelMoveParam[] posArr = new LogicLevelMoveParam[paramList1.Count / elementLength];
                    for (int i = 0; i < posArr.Length; i++)
                    {
                        int step = i * elementLength;
                        var moveParam = new LogicLevelMoveParam();
                        moveParam.destination = new Vector3Int(paramList1[step],
                            paramList1[step + 1],
                            paramList1[step + 2]);
                        moveParam.speedRatio = (float)paramList1[step + 3] / 100;
                        posArr[i] = moveParam;
                    }
                    _navCom.TryStartNav(posArr, false, true, !_isInHouse);
                    break;
                default:
                    break;
            }
        }

        private bool IsCurActComplete()
        {
            switch (_curActCfg.Type)
            {
                case LgLevelRoutineActType.PlayAnimation:
                    IReadOnlyList<int> paramList1 = _curActCfg.ParamList[0];
                    int actionMilliSec = paramList1[1];
                    return _entity.region.level.levelFrame - _actStartFrame >= LgLevelConvertUtil.MillisecToFrame(actionMilliSec);
                case LgLevelRoutineActType.Navigation:
                    return _navCom.navIsComplete;
                default:
                    LogicLog.LogError($"类型[{_curActCfg.Type}]未实现结束判断。");
                    break;
            }
            return false;
        }

        public void Pause()
        {
            if (isPausing)
                return;
            isPausing = true;
            switch (_curActCfg.Type)
            {
                case LgLevelRoutineActType.PlayAnimation:
                    break;
                case LgLevelRoutineActType.Navigation:
                    _navCom.SetNavEnabled(false);
                    break;
                default:
                    LogicLog.LogError($"类型[{_curActCfg.Type}]未实现Pause。");
                    break;
            }
        }

        public void Resume()
        {
            if (!isPausing)
            {
                return;
            }
            isPausing = false;
            IReadOnlyList<int> paramList1 = _curActCfg.ParamList[0];
            switch (_curActCfg.Type)
            {
                case LgLevelRoutineActType.PlayAnimation:
                    PlayEntityAnimation(paramList1[0]);
                    break;
                case LgLevelRoutineActType.Navigation:
                    _navCom.SetNavEnabled(true);
                    break;
                default:
                    LogicLog.LogError($"类型[{_curActCfg.Type}]未实现Resume。");
                    break;
            }
        }

        private void PlayEntityAnimation(int id)
        {
            _actStartFrame = _entity.region.level.levelFrame;
            _entity.region.NotifyPlayEntityAnimAction(null, _notifyEntityList, id);
        }

        private void NextMove()
        {
            if (_curActCfg.NextId > 0)
            {
                _curActCfg = TableCenter.levelRoutineAct.Get(_curActCfg.NextId);
                DoAction();
            }
            else //脚本结束
            {
                Stop();
            }
        }

        public override void LogicOnUpdate()
        {
            if (_curActCfg != null && !isPausing && !_entity.isFreeze)
            {
                _checkElapsedFrame++;
                if (_checkElapsedFrame >= _checkFrameDuration)
                {
                    _checkElapsedFrame = 0;
                    if (IsCurActComplete())
                    {
                        NextMove();
                    }
                }
            }
        }

        public void Stop()
        {
            if (_navCom != null)
            {
                _navCom.StopAndDestroy();
                _navCom = null;
            }
            _checkElapsedFrame = 0;
            _actStartFrame = 0;
            _curActCfg = null;
            isActive = false;
            isPausing = false;
        }

        public override void OnRelease()
        {
            Stop();
            _isInHouse = false;
            _entity = null;
            _notifyEntityList = null;
        }
    }
}
